package com.just.fun.thread;

import java.util.concurrent.locks.LockSupport;

/**
 * 利用LockSupport类，park和unPark方法
 * （1）wait和notify都是Object中的方法,在调用这两个方法前必须先获得锁对象，但是park不需要获取某个对象的锁就可以锁住线程。
 * （2）notify只能随机选择一个线程唤醒，无法唤醒指定的线程，unpark却可以唤醒一个指定的线程。
 *
 * park()执行过程
 * （1）判断当前线程是否发生中断：
 *
 * 中断：线程继续执行。
 * 未中断：判断counter值。counter值1，表示线程拥有permit，将状态位置为0，线程继续执行；counter值0，表示线程没有permit，线程阻塞。
 * unPark()执行过程
 *
 * （1）记录counter当前状态，将counter置为1（不管状态位值为啥）。
 *
 * （2）根据当前线程状态位信息，判断unPark()对应线程是否挂起。
 *
 * 挂起：执行线程唤醒操作，唤醒后将counter置为0；
 * 未挂起：返回。
 *
 * 线程启动后unPark()操作在park()操作前执行线程仍可继续运行。可避免死锁发生。
 *
 * 底层依赖Unsafe实现。
 *
 * AQS阻塞线程和解除阻塞线程的机制,用LockSupport来实现
 *
 */
public class ThreadSyncABC1 {
    static Thread tA,tB,tC;
    public static void main(String[] args) {
        tA=new Thread(()->{
            for(int i=0;i<10;i++){
                System.out.print("A");
                //唤醒下一个线程B
                LockSupport.unpark(tB);
                //阻塞当前线程
                LockSupport.park();
            }
        });

        tB=new Thread(()->{
            for(int i=0;i<10;i++){
                //阻塞当前线程等待被唤醒
                LockSupport.park();
                System.out.print("B");
                //唤醒下一个线程C
                LockSupport.unpark(tC);
            }
        });

        tC=new Thread(()->{
            for(int i=0;i<10;i++){
                //阻塞当前线程等待被唤醒
                LockSupport.park();
                System.out.print("C");
                //唤醒下一个线程A
                LockSupport.unpark(tA);

            }
        });

        tA.start();
        tB.start();
        tC.start();
    }
}
